package paycenter

import (
	"fmt"
	"gmanager/app/constants"
	"gmanager/app/utils"
	"strings"

	"github.com/gogf/gf/container/gmap"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/text/gregex"
	"github.com/gogf/gf/util/gconv"
)

// 提现处理
type WithdrawOrderReq struct {
	Uid     string `p:"uid"  v:"required|integer|min:10000"`
	AppID   string `p:"app_id" v:"required"`
	OrderID string `p:"order_id v:"required"`
}

// 用户
type UserReq struct {
	Uid   string `p:"uid"  v:"required|integer|min:10000"`
	AppID string `p:"app_id" v:"required"`
}

// 用户选择支付请求
type RechargeChannelReq struct {
	Uid       string `p:"uid"  v:"required|integer|min:10000"`
	AppID     string `p:"app_id" v:"required"`
	ChannelID string `p:"channel_id" v:"required|integer|min:1"`
}

// 用户下单
type RechargeOrderReq struct {
	Uid       string `p:"uid"  v:"required|integer|min:10000"`
	AppID     string `p:"app_id" v:"required"`
	ShopID    string `p:"shop_id" v:"required|integer|min:1"`
	ChannelID string `p:"channel_id" v:"required|integer|min:1"`
}

// 通道接口
type IPayement interface {
	GetID() int
	GetName() string
	GetNotifyURL(payType string) string

	// 支付下单
	GetPayOrder(record g.Map, r *ghttp.Request)
	// 支付下单回调
	NotifyPay(r *ghttp.Request)

	// 提现下单
	GetDrawOrder(record gdb.Record, r *ghttp.Request)
	// 提现下单回调
	NotifyDraw(r *ghttp.Request)

	// 查询订单状态
	GetQuery(record gdb.Record) (*gmap.Map, error)
	// 查询代付余额
	GetBalance() (g.List, error)
}

// 用户下单-充值
func PayementOrder(user gdb.Record, shop gdb.Record, channel gdb.Record, r *ghttp.Request) {

	// 获取支付方式关联的支付渠道
	results, err := GetChannelConf(channel["id"].Int())
	if err != nil {
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err,
		})
	}

	// 为此次下单生成订单号
	order := g.Map{
		"uid":      user["id"].String(),
		"order_id": utils.GetOrderNo(constants.PAY_MODE_PAY_TYPE),
		"money":    shop["money"],
		"shop_id":  shop["id"],
		"app_id":   user["channel"].String(),
	}
	// 循环遍历支付渠道获取支付订单
	for _, payconf := range results {

		// 获取支付渠道
		pay, err := getPay(payconf)
		if err != nil {
			r.Response.WriteJsonExit(g.Map{
				"code": -1,
				"msg":  err,
			})
		}
		pay.GetPayOrder(order, r)
	}
}

// 用户下单-提现
func WithdrawOrder(user gdb.Record, order gdb.Record, payconf gdb.Record, r *ghttp.Request) {
	pay, err := getPay(payconf)
	if err != nil {
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})
	}
	pay.GetDrawOrder(order, r)
}

// 取得通道对象
func getPay(record gdb.Record) (IPayement, error) {
	j, err := gjson.DecodeToJson(record["params"].String())
	if err != nil {
		return nil, gerror.New("通道匹配异常：请检查json配置：" + err.Error())
	}
	if strings.ToLower(record["conf_name"].String()) == "bmartpay" {
		return &Bmartpay{
			Name: record["conf_name"].String(),
			Conf: j,
			ID:   record["id"].Int(),
		}, nil
	} else if strings.ToLower(record["conf_name"].String()) == "fakgt" {
		return &Fakgt{
			Name: record["conf_name"].String(),
			Conf: j,
			ID:   record["id"].Int(),
		}, nil
	}
	return nil, gerror.New("通道匹配异常：请检查数据库配置记录和代码是否有匹配上")
}

// 查询代付余额
func GetBalance(payconfs gdb.Result) (g.List, error) {
	var results g.List
	// 循环遍历可用的支付渠道
	for _, payconf := range payconfs {
		// 获取支付渠道
		pay, err := getPay(payconf)
		if err != nil {
			return nil, err
		}
		result, err := pay.GetBalance()
		if err != nil {
			results = append(results, g.Map{
				"id":   payconf["id"].Int(),
				"name": payconf["name"].String(),
				"data": g.Map{
					"balance": 0,
				},
				"msg": err,
			})
		} else {
			results = append(results, g.Map{
				"id":   payconf["id"].Int(),
				"name": payconf["name"].String(),
				"data": result,
				"msg":  "ok",
			})
		}
	}
	return results, nil
}

// 查询订单状态
func GetQuery(payconf gdb.Record) (*gmap.Map, error) {
	// 获取支付渠道
	pay, err := getPay(payconf)
	if err != nil {
		return nil, err
	}
	result, err := pay.GetQuery(payconf)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// 支付下单回调
func NotifyPay(payconf gdb.Record, r *ghttp.Request) {
	// 获取支付渠道
	pay, err := getPay(payconf)
	if err != nil {
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err,
		})
	}
	pay.NotifyPay(r)

}

// 代付下单回调
func NotifyDraw(payconf gdb.Record, r *ghttp.Request) {
	// 获取支付渠道
	pay, err := getPay(payconf)
	if err != nil {
		r.Response.WriteJsonExit(g.Map{
			"code": -1,
			"msg":  err.Error(),
		})
	}
	pay.NotifyDraw(r)
}

func RechargeCheckSign(d g.Map) bool {
	paramStr := fmt.Sprintf("app_id=%s&gap=%s&tx=%s&uid=%s&key=%s", gconv.String(d["app_id"]), gconv.String(300), gconv.String(d["tx"]), gconv.String(d["uid"]), gconv.String(123456))
	md5Sign, _ := gmd5.Encrypt(paramStr)
	if md5Sign != d["sign"] {
		return false
	}
	return true
}

// 查询渠道下绑定的支付方式
func GetChannelConf(channelID int) (gdb.Result, error) {
	sql := `SELECT
	*,
	c.name as conf_name
FROM
	game_pay_conf as c,
	game_pay_conf_channel_rel AS r,
	game_pay_channel AS cn
WHERE
	c.id = r.pay_conf_id
AND 
	r.pay_channel_id = cn.id
AND
	cn.id = ?`
	rows, err := g.DB().GetAll(sql, channelID)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 查询用户下绑定的字段
func GetUserFields(id int) (gdb.Result, error) {
	sql := `SELECT
	f.*,r.value
FROM
	user as u,
	game_pay_user_field_rel AS r,
	game_pay_field AS f 
WHERE
	u.id = r.pay_user_id 
AND r.pay_field_id = f.id
AND u.id=?`
	rows, err := g.DB().GetAll(sql, id)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 查询用户下绑定的字段
func GetUserFieldsValue(id int) (gdb.Result, error) {
	sql := `SELECT
	r.pay_field_id,
	f.name,
	r.value
FROM
	user as u,
	game_pay_user_field_rel AS r,
	game_pay_field AS f 
WHERE
	u.id = r.pay_user_id 
AND r.pay_field_id = f.id
AND u.id=?`
	rows, err := g.DB().GetAll(sql, id)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 查询渠道绑定的字段
func GetChannelFields(channelID int) (gdb.Result, error) {
	sql := `SELECT
	* 
FROM
	game_pay_channel AS c,
	game_pay_channel_field_rel AS r,
	game_pay_field AS f 
WHERE
	c.id = r.pay_channel_id 
AND r.pay_field_id = f.id
AND	c.id=?`
	rows, err := g.DB().GetAll(sql, channelID)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 查询出用户在指定的渠道绑定的所有字段
func GetUserAllBindFields(uid string, appID string, channelID string, payMode int) (gdb.Result, error) {
	sql := `
	SELECT
	channel_fields.*,user_fields.value
FROM
	(
SELECT
	f.* 
FROM
	game_pay_channel AS c,
	game_pay_channel_field_rel AS r,
	game_pay_field AS f 
WHERE
	c.id = r.pay_channel_id 
	AND r.pay_field_id = f.id 
	AND r.pay_mode = ?
	AND c.id = ?
	) AS channel_fields
	LEFT JOIN (
SELECT
	f2.id,r2.value
FROM
	user AS u2,
	game_pay_user_field_rel AS r2,
	game_pay_field AS f2 
WHERE
	u2.id = r2.pay_user_id 
	AND r2.pay_field_id = f2.id 
	AND u2.id = ? 
	AND u2.channel = ? 
	) AS user_fields ON channel_fields.id = user_fields.id`
	rows, err := g.DB().GetAll(sql, payMode, channelID, uid, appID)
	if err != nil {
		return nil, err
	}
	return rows, nil

}

// 查询出用户在指定的渠道内没有绑定的字段
func GetUserNotBindFields(uid string, appID string, channelID string, payMode int) (gdb.Result, error) {
	sql := `SELECT
	f.*
FROM
	game_pay_channel AS c,
	game_pay_channel_field_rel AS r,
	game_pay_field AS f 
WHERE
	c.id = r.pay_channel_id 
	AND r.pay_field_id = f.id
	AND r.pay_mode = ?
	AND c.id = ?
	AND
		f.id not in (SELECT
	f2.id
FROM
	user as u2,
	game_pay_user_field_rel AS r2,
	game_pay_field AS f2 
WHERE
	u2.id = r2.pay_user_id 
AND 
	r2.pay_field_id = f2.id
AND
	u2.id=?
AND
    u2.channel=?)`

	rows, err := g.DB().GetAll(sql, payMode, channelID, uid, appID)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 获得用户绑定的指定字段
func GetUserField(results gdb.Result, name string) string {
	for _, v := range results {
		if v["name"].String() == name {
			return v["value"].String()
		}
	}
	return ""
}

func EditProfile(uid string, appID string, mapFields map[string]string) error {
	if tx, err := g.DB().Begin(); err == nil {
		defer func() {
			if err != nil {
				tx.Rollback()
			} else {
				tx.Commit()
			}
		}()
		// 用户
		user, err := tx.Table("user").Where("id", uid).Where("channel", appID).LockUpdate().One()
		if err != nil {
			return err
		}
		if len(user) == 0 {
			return gerror.New("User is empty")
		}
		// 取消送真金活动
		// if user["is_edit_profile"].Int() == 1 {
		// 	return gerror.New("Profile is edited")
		// }

		// 先删除，后插入
		tx.Table("game_pay_user_field_rel").Where("pay_user_id", user["id"]).Delete()
		for k, v := range mapFields {
			if strings.Index(k, "map[") >= 0 {
				match, _ := gregex.MatchString(`map\[(\d+)\]`, k)

				tx.Table("game_pay_user_field_rel").Data(g.Map{
					"pay_user_id":  user["id"],
					"pay_field_id": match[1],
					"value":        v,
				}).Insert()
			}

		}
		// 取消送真金活动
		// rx, err := tx.Table("user").Where("id", user["id"]).Data(g.Map{
		// 	"is_edit_profile": 1,
		// }).Update()
		// if err != nil {
		// 	return err
		// }
		// rs, err := rx.RowsAffected()
		// if err != nil {
		// 	return err
		// }
		// if rs > 0 {
		// 	utils.PushChangeUserMoney(user["id"].Int(), 10, 10)
		// }
		return nil
	}
	return gerror.New("Edit profile is error")
}
